/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "工程文件.h"
#include <文件/file_文件名数据.h>


#include "A_引擎/引擎.h"
#include "框架/工作区/节点操作.h"





static S_工程文件* gFile = 0;
//static std::string g设置工程目录;


static std::vector<C_节点面板*> g_选择节点;
static uint32					g_节点选择数量 = 0;





typedef struct {
	vec3 pos;
	vec3 rot;
	float32 depth;
	float32 近端;
	float32 远端;
	uint32	投影模式;
}S_摄像机数据文件块;


typedef struct {
	uint32 版本号[2];
	uint64 工程文件类型;
}S_工程文件头;




S_工程文件* f_projectFile_创建() {
	gFile = (S_工程文件*)malloc(sizeof(S_工程文件));
	return gFile;
}

void f_projectFile_销毁(S_工程文件* p) {
	//f_prop_Release(gFile->m_时间区间);
	free(gFile);
}









S_工程文件* f_projectFile_取当前工程文件(bool 创建新文件) {
	if (!gFile) {
		gFile = new S_工程文件;

		f_NodeCtx_set帧区间({ 0, 250 });
		f_NodeCtx_set当前帧(0);

		//gFile->m_时间区间 = {0, 250};
		//gFile->m_时间区间 = f_NodeCtx_get帧().帧区间;
		//gFile->m_当前帧 = f_NodeCtx_get帧().当前帧;
		
	}
	return gFile;
}






void f_projectFile_加载全局状态(FILE* f, uint64 版本) {
	auto 文件块 = f_file_读取文件块(f);

	if (文件块.m_块类型 == E_工程文件块类型::e_工程文件块_全局状态) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;
		if (f_file_版本对比(文件块, S_节点数据::g_低版本号_0, S_节点数据::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(S_节点数据状态::g_网格编辑模式, 下一次读取数据指针);

			下一次读取数据指针 = f_prop_Load(S_节点数据状态::g_骨骼编辑模式, 下一次读取数据指针);

			下一次读取数据指针 = f_prop_Load(S_节点数据状态::g_灯光编辑模式, 下一次读取数据指针);

			下一次读取数据指针 = f_prop_Load(S_节点数据状态::g_3D视口显示模式, 下一次读取数据指针);

			下一次读取数据指针 = f_prop_Load(f_NodeCtx_get帧().当前帧, 下一次读取数据指针);

			下一次读取数据指针 = f_prop_Load(f_NodeCtx_get帧().帧区间, 下一次读取数据指针);

			下一次读取数据指针 = f_prop_Load(f_NodeCtx_get帧().子帧, 下一次读取数据指针);
		}
	}
	
	free(文件块.m_data);
}

void f_projectFile_保存全局状态(FILE* f, uint64 版本) {
	S_文件块 文件块;
	文件块.m_块类型 = E_工程文件块类型::e_工程文件块_全局状态;
	文件块.m_版本号 = 版本;

	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(S_节点数据状态::g_网格编辑模式, 块);
	f_prop_Save(S_节点数据状态::g_骨骼编辑模式, 块);
	f_prop_Save(S_节点数据状态::g_灯光编辑模式, 块);
	f_prop_Save(S_节点数据状态::g_3D视口显示模式, 块);
	f_prop_Save(f_NodeCtx_get帧().当前帧, 块);
	f_prop_Save(f_NodeCtx_get帧().帧区间, 块);
	f_prop_Save(f_NodeCtx_get帧().子帧, 块);


	f_file_保存文件块(f, 文件块, 块);
}

void f_projectFile_设置工程目录(std::string filename) {
	if (filename.empty()) {
		filename = std::filesystem::temp_directory_path().string();
	}
	auto 文件名 = f_file_取无后缀文件名(filename);
	if (文件名 == ".") {
		文件名 = "";
		time_t t = time(0);
		for (uint32 i = 0; i < 8; ++i) {
			uint32 c = ((t>>i*4)&0xf);
			if(c > 9) c += 9;
			文件名 += 48 + c;
		}
	}

	
	S_节点数据::g_工程文件名称 = filename;
	S_节点数据::g_工程文件路径 = f_file_get路径(S_节点数据::g_工程文件名称);
	S_节点数据::g_工程文件节点代码路径 = S_节点数据::g_工程文件路径 + 文件名 + "_资源/";

	f_file_去路径空白字符(S_节点数据::g_工程文件节点代码路径);
	S_节点数据::g_工程文件几何节点代码绝对路径 = S_节点数据::g_工程文件节点代码路径 + "几何/";
	S_节点数据::g_工程文件函数节点代码绝对路径 = S_节点数据::g_工程文件节点代码路径 + "函数/";
	S_节点数据::g_工程文件材质节点代码绝对路径 = S_节点数据::g_工程文件节点代码路径 + "材质/";
	S_节点数据::g_工程文件着色节点代码绝对路径 = S_节点数据::g_工程文件节点代码路径 + "着色/";

	f_file_创建目录(S_节点数据::g_工程文件几何节点代码绝对路径);
	f_file_创建目录(S_节点数据::g_工程文件函数节点代码绝对路径);
	f_file_创建目录(S_节点数据::g_工程文件材质节点代码绝对路径);
	f_file_创建目录(S_节点数据::g_工程文件着色节点代码绝对路径);
}

void f_projectFile_载入(FILE* f) {
	S_框架::g_视口相机.clear();
	S_节点数据::g_选中激活物体.clear();
	f_global_clear激活节点();
	f_NodeView_清除所有视口中的节点();
	f_NodeCtx_清除全局数据();
	f_scene_销毁渲染器纹理(f_NodeCtx_get默认场景(), 1);

	f_projectFile_清除焦点更新节点();
	f_node_释放虚拟体网格();
	
	//f_NodeView_安装节点树后端(f_node_get节点树(0));
	


	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_工程文件块类型::e_工程文件块_文件头) {
		S_引擎::读取加载文件版本号 = 文件块.m_版本号;

		S_工程文件头 工程文件头 = *((S_工程文件头*)文件块.m_data);
		S_框架::版本号[0] = 工程文件头.版本号[0];
		S_框架::版本号[1] = 工程文件头.版本号[1];

		//S_引擎::读取加载文件版本号 = S_框架::版本号[1] << 32 | S_框架::版本号[0];
		

		auto 节点树文件块 = f_file_读取文件块(f);
		if (节点树文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点树) {
			f_node后端_读取所有节点(*S_框架::g_3D视口环境, f);
		}
		free(节点树文件块.m_data);


		f_projectFile_加载全局状态(f, S_引擎::读取加载文件版本号);


		S_框架::g_界面构建->f_加载界面框架(f);
	}
	
	free(文件块.m_data);
}

void f_projectFile_保存(FILE* f) {
	
	f_file_去路径空白字符(S_节点数据::g_工程文件节点代码路径);
	S_节点数据::g_工程文件几何节点代码绝对路径 = S_节点数据::g_工程文件节点代码路径 + "几何/";
	S_节点数据::g_工程文件函数节点代码绝对路径 = S_节点数据::g_工程文件节点代码路径 + "函数/";
	S_节点数据::g_工程文件材质节点代码绝对路径 = S_节点数据::g_工程文件节点代码路径 + "材质/";
	S_节点数据::g_工程文件着色节点代码绝对路径 = S_节点数据::g_工程文件节点代码路径 + "着色/";

	f_file_创建目录(S_节点数据::g_工程文件几何节点代码绝对路径);
	f_file_创建目录(S_节点数据::g_工程文件函数节点代码绝对路径);
	f_file_创建目录(S_节点数据::g_工程文件材质节点代码绝对路径);
	f_file_创建目录(S_节点数据::g_工程文件着色节点代码绝对路径);
	

	S_工程文件头 工程文件头;
	//工程文件头.版本号[0] = S_框架::版本号[0];
	//工程文件头.版本号[1] = S_框架::版本号[1];
	//工程文件头.版本号[0] = S_节点数据::g_文件版本号>>32;
	//工程文件头.版本号[1] = S_节点数据::g_文件版本号;

	//S_文件块 文件块 = f_file_构建文件块信息(E_工程文件块类型::e_工程文件块_文件头, S_框架::版本号[1] << 32 | S_框架::版本号[0]);
	S_文件块 文件块 = f_file_构建文件块信息(E_工程文件块类型::e_工程文件块_文件头, S_节点数据::g_文件版本号);
	
	
	工程文件头.工程文件类型 = f_字符串名称转换("MBT main\0");
	文件块.m_字节数 = sizeof(S_工程文件头);
	文件块.m_data = (uint8*)&工程文件头;
	f_file_保存文件块(f, 文件块);



	//保存节点
	文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点树, S_节点数据::g_文件版本号);
	f_file_保存文件块(f, 文件块);
	f_node后端_写出所有节点(f);


	f_projectFile_保存全局状态(f, 0);

	S_框架::g_界面构建->f_保存界面框架(f);
	
}

bool f_projectFile_保存当前文件() {
	auto 扩展名 = f_file_文件扩展名(S_节点数据::g_工程文件名称);

	if (扩展名 == ".np") {
		f_file_备份保存文件(S_节点数据::g_工程文件名称, f_projectFile_保存);

		/*FILE* f = fopen(S_节点数据::g_工程文件路径.c_str(), "wb");
		if (f) {
			f_projectFile_保存(f);
			fclose(f);
		}*/

		return true;
	}
	return false;
}

void f_projectFile_设置文件保存状态(bool 是否已保存) {
	auto 标题 = f_StringToWString(S_节点数据::g_工程文件名称);
	if (!是否已保存) {
		标题 += L"*";
	}

	for (auto* window : S_框架::g_主窗口) {
		window->f_设置标题(标题);
	}
}

bool on_projectFile_文件打开保存(C_Widget* self, const std::vector<std::string>& filenames, E_对话框类型 方式) {
	C_Widget::g_鼠标样式 = E_鼠标样式::e_鼠标样式_等待;

	switch (方式) {
	case E_对话框类型::e_读取:
		for (auto& path : filenames) {
			//std::cout << "name == " << path << std::endl;
			f_projectFile_设置工程目录(path);
			//path = "I:/TEMP/n2.ms";
			FILE* f = fopen(path.c_str(), "rb");
			if (f) {
				auto 扩展名 = f_file_文件扩展名(path);

				if (扩展名 == ".np") {
					f_projectFile_载入(f);
				}
				else if (扩展名 == ".ms") {
					auto objs = f_load多物体(f, *S_框架::g_3D视口环境);
					auto* 材质 = new S_单色面材质(*S_框架::g_3D视口环境);
					for (auto& ob : objs) {
						f_ob_set材质(ob, 材质);
						S_框架::g_Scene->f_add物体(ob);
					}
				}
				else if (扩展名 == ".ncp") {

				}

				fclose(f);

			}
			else {
				std::cout << "打开文件失败" << std::endl;
			}

		}
		break;
	case E_对话框类型::e_写入:
		for (auto& path : filenames) {
			auto 扩展名 = f_file_文件扩展名(path);

			if (扩展名 == ".np") {
				f_projectFile_设置工程目录(path);
				//S_节点数据::g_工程文件路径 = path;
				//S_节点数据::g_工程文件节点代码路径 = f_file_get路径(path) + f_file_取无后缀文件名(path) + "/";

				f_file_备份保存文件(path, f_projectFile_保存);
			}
			else if (扩展名 == ".ncp") {
				FILE* f = fopen(path.c_str(), "wb");

				if (f) {


					fclose(f);
				}
				else {
					std::cout << "保存文件失败" << std::endl;
				}
			}
			
		}
		break;
	case E_对话框类型::e_关闭:
		break;
	default:
		break;
	}

	
	f_ui_switchRootWidget(S_框架::g_UIGM, 0);
	f_projectFile_设置文件保存状态(true);

	C_Widget::g_鼠标样式 = E_鼠标样式::e_鼠标样式_默认;
	return true;
}


void on_文件菜单项(C_Widget* self, const std::wstring name, uint16 id) {
	std::string path = "I:/TEMP/untitled.ms";

	if (name == L"打开") {
		//f_ui_设置文件对话框类型(S_Core::g_ui文件对话框, E_对话框类型::e_读取);
		f_ui_打开对话框(S_框架::g_UIGM, S_框架::g_ui文件对话框, E_对话框类型::e_读取, on_projectFile_文件打开保存, "I:/TEMP/", ".np");
		//f_ui_switchRootWidget(gUIGM, g文件对话框ID);
	}
	else if (name == L"保存") {
		//f_ui_设置文件对话框类型(S_Core::g_ui文件对话框, E_对话框类型::e_写入);
		f_ui_打开对话框(S_框架::g_UIGM, S_框架::g_ui文件对话框, E_对话框类型::e_写入, on_projectFile_文件打开保存, "I:/TEMP/", ".np");
		//f_ui_switchRootWidget(gUIGM, g文件对话框ID);
	}
	else if (name == L"导入") {
		//f_ui_设置文件对话框类型(S_Core::g_ui文件对话框, E_对话框类型::e_读取);
		f_ui_打开对话框(S_框架::g_UIGM, S_框架::g_ui文件对话框, E_对话框类型::e_读取, on_projectFile_文件打开保存, "I:/TEMP/", ".ms");
	}
	else if (name == L"另存") {
		//f_ui_设置文件对话框类型(S_Core::g_ui文件对话框, E_对话框类型::e_读取);
		f_ui_打开对话框(S_框架::g_UIGM, S_框架::g_ui文件对话框, E_对话框类型::e_写入, on_projectFile_文件打开保存, "I:/TEMP/", ".np");
	}
	else if (name == L"测试导入场景n2") {

	}
}




void f_projectFile_保存节点(C_节点面板** node, uint32 num) {

}



















